#ifndef __SSPROTO_MESSAGE_H
#define __SSPROTO_MESSAGE_H

#ifdef _MSC_VER
#pragma warning(disable: 4251)
#endif

#include <string>
#include <vector>

#include "variant.h"

namespace qb {
namespace proto {

/*
    由于服务端，还不支持直接按List方式传输，暂时只支持map方式传输
*/
class SSPROTOAPI MessageHeader{
	public:
		MessageHeader(){}
		MessageHeader(const MessageHeader& header){ Assign(header); }
		MessageHeader& operator=(const MessageHeader& header){ Assign(header); return (*this); }
		~MessageHeader(){}

		inline const std::string& GetType() const { return type_; }
		inline void SetType(const std::string& type) { type_ = type; }

		inline const std::string& GetSubject() const { return subject_; }
		inline void SetSubject(const std::string& subject) { subject_ = subject; }

		inline const std::string& GetMessageID() const { return message_id_; }
		inline void SetMessageID(const std::string& id) { message_id_ = id; }

		void Clear()
		{
			type_.clear();
			subject_.clear();
			message_id_.clear();
		}
	private:
		void Assign(const MessageHeader& header)
		{
			type_ = header.type_;
			subject_ = header.subject_;
			message_id_ = header.message_id_;
		}
		std::string type_;
		std::string subject_;
		std::string message_id_;
	};

class SSPROTOAPI Message {
public:
    typedef Variant::VarType Type ;
    typedef Variant::Map    Map ;
    typedef Variant::List   List ;
    typedef Variant::Raw    Raw ;

    Message();
    Message(const Message& msg) ;
    ~Message();

    inline int FieldCount() const {return map_values_.size() ;}
    bool GetFieldInfo(int index , const char *& name , Type& type) const ;

    const std::string& GetType() const;
    void SetType(const std::string& type);

    const std::string& GetSubject() const;
    void SetSubject(const std::string& subject);

    const std::string& GetMessageID() const;
    void SetMessageID(const std::string& id);

    Message& operator=(const Message& msg) ;


    void SetBool(const char *name, bool value);

    void SetUInt8(const char *name, uint8_t value);
    void SetUInt16(const char *name, uint16_t value);
    void SetUInt32(const char *name, uint32_t value);
    void SetUInt64(const char *name, uint64_t value);
    void SetInt8(const char *name, int8_t value);
    void SetInt16(const char *name, int16_t value);
    void SetInt32(const char *name, int32_t value);
    void SetInt64(const char *name, int64_t value);
    void SetFloat(const char *name, float value);
    void SetDouble(const char *name, double value);
    void SetString(const char *name, const std::string& value);
    void SetRaw(const char *name, const char *value, size_t size);
    void SetMap(const char * name , const Map& map) ;
    void SetList(const char * name , const List& list) ;

    /*
        这三个函数专门是为了提高性能，推荐使用。Add之后，会返回内部生成的类，然后直接在这个类上面操作
    */
    VariantMap* AddMap(const char *name) ;
    VariantList* AddList(const char *name) ;
    Variant* AddVariant(const char *name) ;

    bool GetBool(const char *name, bool &value) const;
    bool GetUInt8(const char *name, uint8_t &value) const;
    bool GetUInt16(const char *name, uint16_t &value) const;
    bool GetUInt32(const char *name, uint32_t &value) const;
    bool GetUInt64(const char *name, uint64_t &value) const;
    bool GetInt8(const char *name, int8_t &value) const;
    bool GetInt16(const char *name, int16_t &value) const;
    bool GetInt32(const char *name, int32_t &value) const;
    bool GetInt64(const char *name, int64_t &value) const;
    bool GetFloat(const char *name, float &value) const;
    bool GetDouble(const char *name, double &value) const;
    bool GetString(const char *name, std::string& value) const;
    bool GetRaw(const char *name, Raw& value) const;
    bool GetMap(const char *name, Map&value) const;
    bool GetList(const char * name , List& value) const;

    /*
        内存引用模式，必须在Message析构之前，释放引用。
    */
    bool RefString(const char *name, const char *& value, size_t &size) const;
    bool RefRaw(const char *name, const void *& value, size_t &size) const;
    bool RefMap(const char *name, const Map* &value) const;
    bool RefList(const char * name , const List*& value) const;    

    inline Map& MapValue() {return map_values_ ;}
    inline const Map& MapValue() const {return map_values_ ;}

    void Clear() ;



    /*
        兼容旧接口，可能被废弃
    */
    inline int fieldCount() const {return FieldCount() ;}
    inline bool getFieldInfo(int index, std::string &name, Type &type) const
    {
        const char * str = NULL ;
        bool result = GetFieldInfo(index , str , type) ;
        if(result == true)
            name = str ;
        return result ;
    }

    inline const std::string& getType() const {return GetType() ;}
    inline void setType(const std::string& type) {SetType(type) ;}
    
    inline const std::string& getSubject() const {return GetSubject() ;}
    inline void setSubject(const std::string &subject) {SetSubject(subject) ;}

    inline const std::string& getMessageID() const {return GetMessageID() ;}
    inline void setMessageID(const std::string& id) {SetMessageID(id) ;}


    inline void setBool(const std::string &name, bool value) {SetBool(name.c_str() , value) ;}
    inline void setUint8(const std::string &name, uint8_t value) {SetUInt8(name.c_str() , value) ;}
    inline void setUint16(const std::string &name, uint16_t value) {SetUInt16(name.c_str() , value) ;}
    inline void setUint32(const std::string &name, uint32_t value) {SetUInt32(name.c_str() , value) ;}
    inline void setUint64(const std::string &name, uint64_t value) {SetUInt64(name.c_str() , value) ;}
    inline void setInt8(const std::string &name, int8_t value) {SetInt8(name.c_str() , value) ;}
    inline void setInt16(const std::string &name, int16_t value) {SetInt16(name.c_str() , value) ;}
    inline void setInt32(const std::string &name, int32_t value) {SetInt32(name.c_str() , value) ;}
    inline void setInt64(const std::string &name, int64_t value) {SetInt64(name.c_str() , value) ;}
    inline void setFloat(const std::string &name, float value) {SetFloat(name.c_str() , value) ;}
    inline void setDouble(const std::string &name, double value) {SetDouble(name.c_str() , value) ;}
    inline void setString(const std::string &name, const std::string &value) {SetString(name.c_str() , value) ;}
    inline void setRaw(const std::string &name, const char *value, size_t size) {SetRaw(name.c_str() , value , size) ;}
    inline void setMessage(const std::string &name, const Message &value) {SetMap(name.c_str() , value.MapValue()) ;}
    inline void setMap(const std::string &name, const Map &value) {SetMap(name.c_str() , value) ;}
    inline void setList(const std::string& name , const List& value)  {SetList(name.c_str() , value) ;}

    inline bool getBool(const std::string &name, bool &value) const {return GetBool(name.c_str() , value) ;}
    inline bool getUint8(const std::string &name, uint8_t &value) const {return GetUInt8(name.c_str() , value) ;}
    inline bool getUint16(const std::string &name, uint16_t &value) const {return GetUInt16(name.c_str() , value) ;}
    inline bool getUint32(const std::string &name, uint32_t &value) const {return GetUInt32(name.c_str() , value) ;}
    inline bool getUint64(const std::string &name, uint64_t &value) const {return GetUInt64(name.c_str() , value) ;}
    inline bool getInt8(const std::string &name, int8_t &value) const {return GetInt8(name.c_str() , value) ;}
    inline bool getInt16(const std::string &name, int16_t &value) const {return GetInt16(name.c_str() , value) ;}
    inline bool getInt32(const std::string &name, int32_t &value) const {return GetInt32(name.c_str() , value) ;}
    inline bool getInt64(const std::string &name, int64_t &value) const {return GetInt64(name.c_str() , value) ;}
    inline bool getFloat(const std::string &name, float &value) const {return GetFloat(name.c_str() , value) ;}
    inline bool getDouble(const std::string &name, double &value) const {return GetDouble(name.c_str() , value) ;}
    inline bool getString(const std::string &name, std::string &value) const {return GetString(name.c_str() , value) ;}
    inline bool getRaw(const std::string &name, const char *&value, size_t &size) const {return RefRaw(name.c_str() , (const void *&)value , size) ;}
    inline bool getMessage(const std::string &name, Message &value) const 
    {
        value.Clear() ;
        const Map * map = NULL ;
        if(RefMap(name.c_str() , map) == false || map == NULL)
            return false ;

        value.MapValue() = *map ;
        return true ;
    }
    inline bool getList(const std::string& name , List& value) const {return GetList(name.c_str() , value) ;}

    inline bool refRaw(const std::string &name, const void *&value, size_t &size) const {return RefRaw(name.c_str() , value , size) ;}

    inline int encode(void * buffer , size_t size) const {return Encode(buffer , size) ;}
    inline int encodeSize() const {return EncodeSize() ;}
    inline int decode(const void * buffer , size_t size) {return Decode(buffer , size) ;}

    /*
        编码失败，返回-1
        空值，返回-2
        空间不足，返回-3
        否则返回实际编码的长度

        内存中的编码格式和qpid编码格式类型，最开始不带type的一个字节。
    */
    int Encode(void * buffer , size_t size) const;
    int EncodeSize() const ;
    int Decode(const void * buffer , size_t size) ;
    int DecodeHeader(const void * buffer , size_t size) ;
    int DecodeBody(const void * buffer , size_t size) ;

    /*
        测试用，请勿调用
    */
    void RebuildNameTable() ;
private:
    MessageHeader  header_;    
    Map     map_values_ ;

    void copy(const Message& msg)  ;

    /*
        暂时不支持List类型的消息格式
    */
    //List    list_values_ ;
};
}
}

#endif    /** __SSPROTO_MESSAGE_H */
